package com.bsoft.controller.JSON;

import cn.hutool.json.JSONObject;
import cn.org.bjca.anysign.components.bean.message.ExternalAnyWriteInfo;
import cn.org.bjca.anysign.components.bean.message.ExternalEncryptPackageInfo;
import cn.org.bjca.anysign.components.bean.message.MessageBodyReference;
import cn.org.bjca.anysign.terminal.model.AttachmentInfo;
import cn.org.bjca.common.model.DocumentExtType;
import cn.org.bjca.common.model.GeneratePDFInfo;
import cn.org.bjca.seal.esspdf.client.message.ChannelMessage;
import cn.org.bjca.seal.esspdf.client.tools.AnySignClientTool;
import cn.org.bjca.seal.esspdf.client.utils.ClientUtil;
import com.bsoft.mapper.business.InvoicingBoozMapper;
import com.bsoft.mapper.business.MedicareMapper;
import com.bsoft.utils.JSONUtil;
import com.google.gson.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.security.auth.message.AuthException;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Controller
@RequestMapping(value = "JSON/BeiJing_CA")
public class BeiJingCAController {
    private static Logger log = LoggerFactory.getLogger(BeiJingCAController.class);

    @Value("${BeiJingCA.Channel}")
    private String beijing_ca_channel;

    // 添加 volatile 保证多线程环境下的可见性（可选）
    private volatile AnySignClientTool anySignClientTool = null;

    @Autowired
    private InvoicingBoozMapper invoicingBoozMapper;

    /*
     *3.3.2.2 多名多签示例
     * 多个名可以签多个 pdf 文件。
     * 加密包文件大小不能超过 20M
     * 重点注意:MultipartFile[] pdfFiles 必须要前端也传文件类型,并且前端只能一次一个file文件,如果要传多个[{"pdfFiles":文件1},{"pdfFiles":文件2}]
     * ChannelMessage anyWriteDataSign(byte[] encPackage)
     * , consumes = "multipart/form-data"
     */
    @PostMapping(value = "/anyWritePDFSignFacades", consumes = "multipart/form-data")
    public void anyWritePDFSignFacades(
            @RequestParam("encryptPackage") String encryptPackage,
            @RequestParam ("orgId") String orgId,
            @RequestPart("pdfFiles") MultipartFile[] pdfFiles,
            HttpServletResponse response) throws Exception {

        log.info("北京CA:3.3.2.2 多名多签:入参:{}", orgId);
        ChannelMessage message = null;

        Assert.notNull(encryptPackage, "encryptPackage:不能为空");
        Assert.notNull(orgId, "encryptPackage:不能为空");

        Map<String, Object> xtcsMap = invoicingBoozMapper.getXTCS(orgId, "xtcs_exchange_bj_ca_ipport");
        if (ObjectUtils.isEmpty(xtcsMap)) throw new Exception("未获取到北京CA系统IP地址系统参数[xtcs_exchange_bj_ca_ipport]");

        //正式环境改造成获取数据库系统参数 : xtcs_exchange_bj_ca_ipport =192.168.14.173:8002
        String caServer = xtcsMap.get("VAL_PARAM").toString();

        // 初始化客户端工具（双重检查锁定）
        if (anySignClientTool == null) {
            synchronized (this) {
                if (anySignClientTool == null) {

                    if (StringUtils.isEmpty(caServer)) {
                        throw new AuthException("请检查北京CA系统参数[xtcs_exchange_bj_ca_ipport]是否维护!");
                    }
                    anySignClientTool = new AnySignClientTool(caServer);
                    anySignClientTool.setTimeout(50000);
                    log.info("初始化 AnySignClientTool 成功: {}", caServer);
                }
            }
        }

        List<ExternalAnyWriteInfo> externalAnyWriteInfoList = new ArrayList<ExternalAnyWriteInfo>();

        //原pdf容器
        List<GeneratePDFInfo> generatePDFInfoList = new ArrayList<GeneratePDFInfo>();

        try {
            //1.组装原文pdf数据
            for (MultipartFile pdfFile : pdfFiles) {
                log.info("总上传PDF数量:{},上传PDF文件:{}, 大小:{} MB,实际长度:{} bytes",pdfFiles.length,pdfFile.getOriginalFilename(),String.format("%.2f",pdfFile.getSize()/(1024.0 * 1024)),pdfFile.getSize());

                if (pdfFile.getSize() > 30*1024*1024) throw new Exception("单个文件不能大于20m");
                GeneratePDFInfo generatePDFInfo = new GeneratePDFInfo();
                generatePDFInfo.setDocContent(pdfFile.getBytes());
                generatePDFInfo.setDocumentExtType(DocumentExtType.PDF);
                generatePDFInfoList.add(generatePDFInfo);
            }

            //2.组装加密包数据
            // byte[] encPackage = JSONUtil.toJson(encryptPackage).getBytes(StandardCharsets.UTF_8);
            byte[] encPackage = encryptPackage.getBytes(StandardCharsets.UTF_8);
            ExternalEncryptPackageInfo encryptPackageInfo = new ExternalEncryptPackageInfo(encPackage);

            List<ExternalEncryptPackageInfo> encryptPackageInfoList = new ArrayList<ExternalEncryptPackageInfo>();
            encryptPackageInfoList.add(encryptPackageInfo);

            //3.汇总组装数据
            ExternalAnyWriteInfo externalAnyWriteInfo = new ExternalAnyWriteInfo();
            //设置渠道号 平昌人民医院 正式 : 25070554
            externalAnyWriteInfo.setChannel(beijing_ca_channel);
            externalAnyWriteInfo.setEncryptPackageInfoList(encryptPackageInfoList);
            externalAnyWriteInfo.setGeneratePDFInfoList(generatePDFInfoList);

            externalAnyWriteInfoList.add(externalAnyWriteInfo);



            message = anySignClientTool.anyWritePDFSignFacade(externalAnyWriteInfoList);

            //改造部分
            log.info("北京CA:3.3.2.2 多名多签:处理结果:{}", "200".equals(message.getStatusCode()) ? message.getStatusCode():JSONUtil.toJson(message));
            // 构建响应结果Map
            Map<String, Object> result = new HashMap<>();
            // 处理200状态（成功）
            if ("200".equals(message.getStatusCode())) {
                List<MessageBodyReference> fileList = message.getMessageBodyReferenceList();
                if (!CollectionUtils.isEmpty(fileList)) {
                    // 创建数组存储每个PDF的Base64数据和文件名
                    List<Map<String, String>> pdfArray = new ArrayList<>();

                    for (MessageBodyReference ref : fileList) {
                        // 对单个PDF二进制数据进行Base64加密
                        String base64Data = Base64.getEncoder().encodeToString(ref.getFileBty());

                        // 生成文件名
                        String fileName = ref.getFileUniqueId() != null ? ref.getFileUniqueId() + ".pdf" : "signed_" + System.currentTimeMillis() + ".pdf";
                        // 存储单个PDF的信息
                        Map<String, String> pdfInfo = new HashMap<>();
                        pdfInfo.put("fileName", fileName);
                        pdfInfo.put("base64Data", base64Data);
                        pdfArray.add(pdfInfo);
                    }

                    // 构建成功响应（数组形式返回）
                    result.put("status", "200");
                    result.put("data", pdfArray); // 数组数据
                    result.put("count", pdfArray.size()); // 文件数量
                    result.put("message", "处理成功");
                } else {
                    result.put("status", "500");
                    result.put("message", "未获取到签名文件");
                }
            } else {
                // 非200状态处理
                result.put("status", "500");
                result.put("message", "处理失败，状态码：" + message.getStatusCode());
            }
            // 返回JSON响应
            response.setContentType("application/json;charset=utf-8");
            // 增加CORS头
            //response.setHeader("Access-Control-Allow-Origin", "*");
            //response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
            try (PrintWriter writer = response.getWriter()) {
                writer.write(JSONUtil.toJson(result));
            }

        } catch (Exception e) {
            log.error("北京CA:3.3.2.2 多名多签:处理异常", e);
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

            // 增加CORS头
            //response.setHeader("Access-Control-Allow-Origin", "*");
            //response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
            try (PrintWriter writer = response.getWriter()) {
                Map<String, Object> error = new HashMap<>();
                error.put("status", "500");
                error.put("message", e.getMessage());
                writer.write(JSONUtil.toJson(error));
            } catch (IOException ex) {
                log.error("错误信息写入失败", ex);
            }
        }
    }

}
